package com.uniledger.exchange.model;

import android.text.TextUtils;
import android.util.Log;

import com.ihsanbal.logging.Level;
import com.ihsanbal.logging.Logger;
import com.ihsanbal.logging.LoggingInterceptor;
import com.uniledger.commonlib.util.NumberUtils;
import com.uniledger.exchange.BuildConfig;
import com.uniledger.exchange.UniApp;
import com.uniledger.exchange.model.api.Api;
import com.uniledger.exchange.model.rx.RxException;
import com.uniledger.exchange.model.rx.RxSchedulers;

import org.reactivestreams.Publisher;
import org.stellar.sdk.KeyPair;

import java.util.Currency;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import me.pushy.sdk.Pushy;
import me.pushy.sdk.util.exceptions.PushyException;
import okhttp3.OkHttpClient;
import okhttp3.internal.platform.Platform;

public class OkSingleton {

    private static final int DEFAULT_TIMEOUT = 15000;

    private OkHttpClient client;

    private String token;

    /**
     * 资产类型
     */
    private Currency assetCurrency;

    /**
     * 资产余额
     */
    private String assetBalance;

    /**
     * 自己的密钥对
     */
    private KeyPair sourceKeyPair;
    /**
     * 资产发行方
     */
    private KeyPair issuingKeyPair;

    private KeyPair baseKeyPair;

    public KeyPair getIssuingKeyPair() {
        return issuingKeyPair;
    }

    public void setIssuingKeyPair(KeyPair baseKeyPair) {
        this.issuingKeyPair = baseKeyPair;
    }

    public void setSourceKeyPair(KeyPair sourceKeyPair) {
        this.sourceKeyPair = sourceKeyPair;
    }

    public KeyPair getSourceKeyPair() {
        return sourceKeyPair;
    }

    public KeyPair getBaseKeyPair() {
        return baseKeyPair;
    }

    public void setBaseKeyPair(KeyPair baseKeyPair) {
        this.baseKeyPair = baseKeyPair;
    }

    private OkSingleton() {

        LoggingInterceptor loggingInterceptor = new LoggingInterceptor.Builder()
                .loggable(BuildConfig.DEBUG)
                .setLevel(Level.BASIC)
                .log(Platform.INFO)
                .request("Request")
                .loggable(BuildConfig.DEBUG)
                .response("Response")
                .addHeader("version", BuildConfig.VERSION_NAME)
//                .addQueryParam("query", "0")
                .enableAndroidStudio_v3_LogsHack(true) /* enable fix for logCat logging issues with pretty format */
                .logger(new Logger() {
                    @Override
                    public void log(int level, String tag, String msg) {
                        Log.w(tag, msg);
                    }
                })
                .executor(Executors.newSingleThreadExecutor())
                .build();

        client = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .addInterceptor(new AuthorizationInterceptor())
//                .addInterceptor(new EncryptInterceptor())
                .readTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
                .build();
    }

    private static class SingletonInstance {
        private static final OkSingleton INSTANCE = new OkSingleton();
    }

    public static OkSingleton getInstance() {
        return SingletonInstance.INSTANCE;
    }


    public void setToken(String token) {
        this.token = token;
        Flowable.create(new FlowableOnSubscribe<String>() {
            @Override
            public void subscribe(FlowableEmitter<String> emitter) throws Exception {
                try {
                    // Assign a unique token to this device
                    String deviceToken = Pushy.register(UniApp.getInstance());
                    // Log it for debugging purposes
                    Log.d("MyApp", "Pushy device token: " + deviceToken);
                    emitter.onNext(deviceToken);
                    emitter.onComplete();
                } catch (PushyException e) {
                    emitter.onError(e);
                }
            }
        }, BackpressureStrategy.MISSING)
                .flatMap(new Function<String, Publisher<HttpResult>>() {
                    @Override
                    public Publisher<HttpResult> apply(String s) throws Exception {
                        return Api.getService().pushToken(s);
                    }
                })
                .compose(RxSchedulers.io_main())
                .subscribe(new Consumer<HttpResult>() {
                    @Override
                    public void accept(HttpResult httpResult) throws Exception {

                    }
                }, new RxException<>(new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {

                    }
                }));
    }

    public String getToken() {
        if (TextUtils.isEmpty(token))
            return "Bearer ";
        return "Bearer " + token;
    }

    public void setAssetCurrency(String assetCurrency) {
        Currency currency = Currency.getInstance(assetCurrency);
        com.orhanobut.logger.Logger.d(currency.getCurrencyCode());
        com.orhanobut.logger.Logger.d(currency.getSymbol());
        this.assetCurrency = currency;
    }

    public void setAssetBalance(String assetBalance) {
        this.assetBalance = NumberUtils.formatRate(assetBalance);
    }

    private Currency getAssetCurrency() {
        return assetCurrency;
    }

    public String getCurrencyCode() {
        return getAssetCurrency().getCurrencyCode();
    }

    public String getSymbol() {
        return getAssetCurrency().getSymbol();
    }

    public String getAssetBalance() {
        return assetBalance;
    }

    public OkHttpClient getClient() {
        return client;
    }
}
